//	VirtualDub - Video processing and capture application
//	Copyright (C) 1998-2003 Avery Lee
//
//	This program is free software; you can redistribute it and/or modify
//	it under the terms of the GNU General Public License as published by
//	the Free Software Foundation; either version 2 of the License, or
//	(at your option) any later version.
//
//	This program is distributed in the hope that it will be useful,
//	but WITHOUT ANY WARRANTY; without even the implied warranty of
//	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//	GNU General Public License for more details.
//
//	You should have received a copy of the GNU General Public License
//	along with this program; if not, write to the Free Software
//	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "stdafx.h"
#include "DubOutput.h"
#include <vd2/system/error.h>
#include <list>
#include "AVIOutput.h"
#include "AVIOutputFile.h"
#include "AVIOutputFLM.h"
#include "AVIOutputGIF.h"
#include "AVIOutputWAV.h"
#include "AVIOutputRaw.h"
#include "AVIOutputImages.h"
#include "AVIOutputStriped.h"
#include "AVIOutputPreview.h"
#include "AVIOutputSegmented.h"

///////////////////////////////////////////

extern "C" unsigned long version_num;
extern uint32 VDPreferencesGetAVIAlignmentThreshold();
extern void VDPreferencesGetAVIIndexingLimits(uint32& superindex, uint32& subindex);

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputFileSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputFileSystem::VDAVIOutputFileSystem()
	: mbAllowCaching(false)
	, mbAllowIndexing(true)
	, mbUse1GBLimit(false)
	, mCurrentSegment(0)
	, mBufferSize(0)
	, mAlignment(0)
{
}

VDAVIOutputFileSystem::~VDAVIOutputFileSystem() {
}

void VDAVIOutputFileSystem::SetCaching(bool bAllowOSCaching) {
	mbAllowCaching = bAllowOSCaching;
}

void VDAVIOutputFileSystem::SetIndexing(bool bAllowHierarchicalExtensions) {
	mbAllowIndexing = bAllowHierarchicalExtensions;
}

void VDAVIOutputFileSystem::Set1GBLimit(bool bUse1GBLimit) {
	mbUse1GBLimit = bUse1GBLimit;
}

void VDAVIOutputFileSystem::SetBuffer(int bufferSize) {
	mBufferSize = bufferSize;
}

void VDAVIOutputFileSystem::SetTextInfo(const std::list<std::pair<uint32, VDStringA> >& info) {
	mTextInfo = info;
}

IVDMediaOutput *VDAVIOutputFileSystem::CreateSegment() {
	VDASSERT(mBufferSize > 0);

	vdautoptr<IVDMediaOutputAVIFile> pOutput(VDCreateMediaOutputAVIFile());

	if (!mbAllowCaching)
		pOutput->disable_os_caching();

	if (!mbAllowIndexing)
		pOutput->disable_extended_avi();

	VDStringW s(mSegmentBaseName);

	if (mSegmentDigits) {
		VDStringW temp;
		temp.sprintf(L".%0*d", mSegmentDigits, mCurrentSegment++);
		s += temp;
		s += mSegmentExt;

		pOutput->setSegmentHintBlock(true, NULL, 1);
	}

	if (!mVideoFormat.empty()) {
		IVDMediaOutputStream *pVideoOut = pOutput->createVideoStream();
		pVideoOut->setFormat(&mVideoFormat[0], mVideoFormat.size());
		pVideoOut->setStreamInfo(mVideoStreamInfo);
		pOutput->setAlignment(0, mAlignment);
	}

	if (!mAudioFormat.empty()) {
		IVDMediaOutputStream *pAudioOut = pOutput->createAudioStream();
		pAudioOut->setFormat(&mAudioFormat[0], mAudioFormat.size());
		pAudioOut->setStreamInfo(mAudioStreamInfo);
	}

	if (!mTextInfo.empty()) {
		tTextInfo::const_iterator it(mTextInfo.begin()), itEnd(mTextInfo.end());

		for(; it!=itEnd; ++it)
			pOutput->setTextInfo((*it).first, (*it).second.c_str());
	}

	pOutput->setBuffering(mBufferSize, mBufferSize >> 2);
	pOutput->setInterleaved(mbInterleaved);

	char buf[80];

	sprintf(buf, "VirtualDub build %d/%s", version_num,
#ifdef _DEBUG
		"debug"
#else
		"release"
#endif
				);

	pOutput->setHiddenTag(buf);

	uint32 superIndexLimit, subIndexLimit;
	VDPreferencesGetAVIIndexingLimits(superIndexLimit, subIndexLimit);

	pOutput->setIndexingLimits(superIndexLimit, subIndexLimit);

	pOutput->init(s.c_str());

	return pOutput.release();
}

void VDAVIOutputFileSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<IVDMediaOutputAVIFile> pFileSegment(static_cast<IVDMediaOutputAVIFile *>(pSegment));
	if (mSegmentDigits)
		pFileSegment->setSegmentHintBlock(bLast, NULL, 1);
	pFileSegment->finalize();
}

void VDAVIOutputFileSystem::SetFilename(const wchar_t *pszFilename) {
	mSegmentBaseName	= pszFilename;
	mSegmentDigits		= 0;
}

void VDAVIOutputFileSystem::SetFilenamePattern(const wchar_t *pszFilename, const wchar_t *pszExt, int nMinimumDigits) {
	mSegmentBaseName	= pszFilename;
	mSegmentExt			= pszExt;
	mSegmentDigits		= nMinimumDigits;
}

void VDAVIOutputFileSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);

	if (uint32 alignmentThreshold = VDPreferencesGetAVIAlignmentThreshold()) {
		const BITMAPINFOHEADER& bih = *(const BITMAPINFOHEADER *)pFormat;
		switch(bih.biCompression) {
		case BI_RGB:
		case BI_BITFIELDS:
		case 'YVYU':	// UYVY
		case '2YUY':	// YUY2
		case 'VYUY':	// YUYV
		case 'UYVY':	// YVYU
		case '21VY':	// YV12
		case '024I':	// I420
		case 'VUYI':	// IYUV
		case '9UVY':	// YVU9
		case '61VY':	// YV16
		case '  8Y':	// Y8
		case '008Y':	// Y800
		case '112Y':	// Y211
		case 'P14Y':	// Y41P
		case 'VUYA':	// AYUV
			uint32 imageSize = bih.biSizeImage;

			if (!imageSize)		// This should only be true for BI_RGB, really.
				imageSize = (((bih.biWidth * bih.biBitCount + 31) >> 5) << 2) * abs(bih.biHeight);

			if (imageSize >= alignmentThreshold)
				mAlignment = 512;
			break;
		}
	}
}

void VDAVIOutputFileSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
	mbInterleaved = bInterleaved;
}

bool VDAVIOutputFileSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputFileSystem::AcceptsAudio() {
	return true;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputStripedSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputStripedSystem::VDAVIOutputStripedSystem(const wchar_t *filename)
	: mbUse1GBLimit(false)
	, mpStripeSystem(new AVIStripeSystem(VDTextWToA(filename, -1).c_str()))
{
}

VDAVIOutputStripedSystem::~VDAVIOutputStripedSystem() {
}

void VDAVIOutputStripedSystem::Set1GBLimit(bool bUse1GBLimit) {
	mbUse1GBLimit = bUse1GBLimit;
}

IVDMediaOutput *VDAVIOutputStripedSystem::CreateSegment() {
	vdautoptr<AVIOutputStriped> pFile(new AVIOutputStriped(mpStripeSystem));

	if (!pFile)
		throw MyMemoryError();

	pFile->set_1Gb_limit();
	return pFile.release();
}

void VDAVIOutputStripedSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputStriped> pFile(static_cast<AVIOutputStriped *>(pSegment));

	pFile->finalize();
}

void VDAVIOutputStripedSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
}

void VDAVIOutputStripedSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
}

bool VDAVIOutputStripedSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputStripedSystem::AcceptsAudio() {
	return true;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputWAVSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputWAVSystem::VDAVIOutputWAVSystem(const wchar_t *pszFilename)
	: mFilename(pszFilename)
	, mBufferSize(1048576)
{
}

VDAVIOutputWAVSystem::~VDAVIOutputWAVSystem() {
}

void VDAVIOutputWAVSystem::SetBuffer(int bufferSize) {
	mBufferSize = bufferSize;
}

IVDMediaOutput *VDAVIOutputWAVSystem::CreateSegment() {
	vdautoptr<AVIOutputWAV> pOutput(new AVIOutputWAV);

	pOutput->createAudioStream()->setFormat(&mAudioFormat[0], mAudioFormat.size());

	pOutput->setBufferSize(mBufferSize);

	pOutput->init(mFilename.c_str());

	return pOutput.release();
}

void VDAVIOutputWAVSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputWAV> pFile(static_cast<AVIOutputWAV *>(pSegment));

	pFile->finalize();
}

void VDAVIOutputWAVSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
}

void VDAVIOutputWAVSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
}

bool VDAVIOutputWAVSystem::AcceptsVideo() {
	return false;
}

bool VDAVIOutputWAVSystem::AcceptsAudio() {
	return true;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputRawSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputRawSystem::VDAVIOutputRawSystem(const wchar_t *pszFilename)
	: mFilename(pszFilename)
	, mBufferSize(1048576)
{
}

VDAVIOutputRawSystem::~VDAVIOutputRawSystem() {
}

void VDAVIOutputRawSystem::SetBuffer(int bufferSize) {
	mBufferSize = bufferSize;
}

IVDMediaOutput *VDAVIOutputRawSystem::CreateSegment() {
	vdautoptr<AVIOutputRaw> pOutput(new AVIOutputRaw);

	pOutput->createAudioStream()->setFormat(&mAudioFormat[0], mAudioFormat.size());

	pOutput->setBufferSize(mBufferSize);

	pOutput->init(mFilename.c_str());

	return pOutput.release();
}

void VDAVIOutputRawSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputRaw> pFile(static_cast<AVIOutputRaw *>(pSegment));

	pFile->finalize();
}

void VDAVIOutputRawSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
}

void VDAVIOutputRawSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
}

bool VDAVIOutputRawSystem::AcceptsVideo() {
	return false;
}

bool VDAVIOutputRawSystem::AcceptsAudio() {
	return true;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputImagesSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputImagesSystem::VDAVIOutputImagesSystem()
{
}

VDAVIOutputImagesSystem::~VDAVIOutputImagesSystem() {
}

IVDMediaOutput *VDAVIOutputImagesSystem::CreateSegment() {
	vdautoptr<AVIOutputImages> pOutput(new AVIOutputImages(mSegmentPrefix.c_str(), mSegmentSuffix.c_str(), mSegmentDigits, mFormat, mQuality));

	if (!mVideoFormat.empty())
		pOutput->createVideoStream()->setFormat(&mVideoFormat[0], mVideoFormat.size());

	if (!mAudioFormat.empty())
		pOutput->createAudioStream()->setFormat(&mAudioFormat[0], mAudioFormat.size());

	pOutput->init(NULL);

	return pOutput.release();
}

void VDAVIOutputImagesSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputImages> pFile(static_cast<AVIOutputImages *>(pSegment));
	pFile->finalize();
}

void VDAVIOutputImagesSystem::SetFilenamePattern(const wchar_t *pszPrefix, const wchar_t *pszSuffix, int nMinimumDigits) {
	mSegmentPrefix		= pszPrefix;
	mSegmentSuffix		= pszSuffix;
	mSegmentDigits		= nMinimumDigits;
}

void VDAVIOutputImagesSystem::SetFormat(int format, int quality) {
	mFormat = format;
	mQuality = quality;
}

void VDAVIOutputImagesSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
}

void VDAVIOutputImagesSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
}

bool VDAVIOutputImagesSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputImagesSystem::AcceptsAudio() {
	return false;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputFilmstripSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputFilmstripSystem::VDAVIOutputFilmstripSystem(const wchar_t *filename)
	: mFilename(filename)
{
}

VDAVIOutputFilmstripSystem::~VDAVIOutputFilmstripSystem() {
}

IVDMediaOutput *VDAVIOutputFilmstripSystem::CreateSegment() {
	vdautoptr<AVIOutputFLM> pOutput(new AVIOutputFLM());

	if (!mVideoFormat.empty()) {
		IVDMediaOutputStream *pOutputStream = pOutput->createVideoStream();
		
		pOutputStream->setFormat(&mVideoFormat[0], mVideoFormat.size());
		pOutputStream->setStreamInfo(mVideoStreamInfo);
	}

	pOutput->init(mFilename.c_str());

	return pOutput.release();
}

void VDAVIOutputFilmstripSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputFLM> pFile(static_cast<AVIOutputFLM *>(pSegment));
	pFile->finalize();
}

void VDAVIOutputFilmstripSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
}

void VDAVIOutputFilmstripSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
}

bool VDAVIOutputFilmstripSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputFilmstripSystem::AcceptsAudio() {
	return false;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputGIFSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputGIFSystem::VDAVIOutputGIFSystem(const wchar_t *filename)
	: mFilename(filename)
	, mLoopCount(0)
{
}

VDAVIOutputGIFSystem::~VDAVIOutputGIFSystem() {
}

IVDMediaOutput *VDAVIOutputGIFSystem::CreateSegment() {
	vdautoptr<IVDAVIOutputGIF> pOutput(VDCreateAVIOutputGIF());

	pOutput->SetLoopCount(mLoopCount);

	AVIOutput *pAVIOut = pOutput->AsAVIOutput();
	if (!mVideoFormat.empty()) {
		IVDMediaOutputStream *pOutputStream = pAVIOut->createVideoStream();
		
		pOutputStream->setFormat(&mVideoFormat[0], mVideoFormat.size());
		pOutputStream->setStreamInfo(mVideoStreamInfo);
	}

	pAVIOut->init(mFilename.c_str());

	pOutput.release();

	return pAVIOut;
}

void VDAVIOutputGIFSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputFLM> pFile(static_cast<AVIOutputFLM *>(pSegment));
	pFile->finalize();
}

void VDAVIOutputGIFSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
}

void VDAVIOutputGIFSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
}

bool VDAVIOutputGIFSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputGIFSystem::AcceptsAudio() {
	return false;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputPreviewSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputPreviewSystem::VDAVIOutputPreviewSystem()
{
}

VDAVIOutputPreviewSystem::~VDAVIOutputPreviewSystem() {
}

IVDMediaOutput *VDAVIOutputPreviewSystem::CreateSegment() {
	vdautoptr<AVIOutputPreview> pOutput(new AVIOutputPreview);

	if (!mVideoFormat.empty())
		pOutput->createVideoStream()->setFormat(&mVideoFormat[0], mVideoFormat.size());

	if (!mAudioFormat.empty())
		pOutput->createAudioStream()->setFormat(&mAudioFormat[0], mAudioFormat.size());

	pOutput->init(NULL);

	return pOutput.release();
}

void VDAVIOutputPreviewSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputPreview> pFile(static_cast<AVIOutputPreview *>(pSegment));
	pFile->finalize();
}

void VDAVIOutputPreviewSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
}

void VDAVIOutputPreviewSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
}

bool VDAVIOutputPreviewSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputPreviewSystem::AcceptsAudio() {
	return true;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputNullVideoAnalysisSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputNullVideoSystem::VDAVIOutputNullVideoSystem()
{
}

VDAVIOutputNullVideoSystem::~VDAVIOutputNullVideoSystem() {
}

IVDMediaOutput *VDAVIOutputNullVideoSystem::CreateSegment() {
	vdautoptr<AVIOutputNull> pOutput(new AVIOutputNull);

	if (!mVideoFormat.empty())
		pOutput->createVideoStream()->setFormat(&mVideoFormat[0], mVideoFormat.size());

	pOutput->init(NULL);

	return pOutput.release();
}

void VDAVIOutputNullVideoSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<AVIOutputNull> pFile(static_cast<AVIOutputNull *>(pSegment));
	pFile->finalize();
}

void VDAVIOutputNullVideoSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
}

void VDAVIOutputNullVideoSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
}

bool VDAVIOutputNullVideoSystem::AcceptsVideo() {
	return true;
}

bool VDAVIOutputNullVideoSystem::AcceptsAudio() {
	return false;
}

///////////////////////////////////////////////////////////////////////////
//
//	VDAVIOutputSegmentedSystem
//
///////////////////////////////////////////////////////////////////////////

VDAVIOutputSegmentedSystem::VDAVIOutputSegmentedSystem(IVDDubberOutputSystem *pSystem, bool intervalIsSeconds, double interval, double preloadInSeconds, sint64 max_bytes, sint64 max_frames)
	: mpChildSystem(pSystem)
	, mbIntervalIsSeconds(intervalIsSeconds)
	, mInterval(interval)
	, mPreload(preloadInSeconds)
	, mMaxBytes(max_bytes)
	, mMaxFrames(max_frames)
{
}

VDAVIOutputSegmentedSystem::~VDAVIOutputSegmentedSystem() {
}

IVDMediaOutput *VDAVIOutputSegmentedSystem::CreateSegment() {
	double interval = mInterval;

	if (mbIntervalIsSeconds) {
		interval *= (double)mVideoStreamInfo.dwRate / (double)mVideoStreamInfo.dwScale;
		if (interval < 1.0)
			interval = 1.0;
	}

	vdautoptr<IVDMediaOutput> pOutput(VDCreateMediaOutputSegmented(mpChildSystem, interval, mPreload, mMaxBytes, mMaxFrames));

	if (!mVideoFormat.empty()) {
		IVDMediaOutputStream *pVideoOut = pOutput->createVideoStream();
		pVideoOut->setFormat(&mVideoFormat[0], mVideoFormat.size());
		pVideoOut->setStreamInfo(mVideoStreamInfo);
	}

	if (!mAudioFormat.empty()) {
		IVDMediaOutputStream *pAudioOut = pOutput->createAudioStream();
		pAudioOut->setFormat(&mAudioFormat[0], mAudioFormat.size());
		pAudioOut->setStreamInfo(mAudioStreamInfo);
	}

	pOutput->init(NULL);

	return pOutput.release();
}

void VDAVIOutputSegmentedSystem::CloseSegment(IVDMediaOutput *pSegment, bool bLast) {
	vdautoptr<IVDMediaOutput> pSegment2(pSegment);
	pSegment2->finalize();
}

void VDAVIOutputSegmentedSystem::SetVideo(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat) {
	mVideoStreamInfo = asi;
	mVideoFormat.resize(cbFormat);
	memcpy(&mVideoFormat[0], pFormat, cbFormat);
	mpChildSystem->SetVideo(asi, pFormat, cbFormat);
}

void VDAVIOutputSegmentedSystem::SetAudio(const AVIStreamHeader_fixed& asi, const void *pFormat, int cbFormat, bool bInterleaved) {
	mAudioStreamInfo = asi;
	mAudioFormat.resize(cbFormat);
	memcpy(&mAudioFormat[0], pFormat, cbFormat);
	mpChildSystem->SetAudio(asi, pFormat, cbFormat, bInterleaved);
}

bool VDAVIOutputSegmentedSystem::AcceptsVideo() {
	return mpChildSystem->AcceptsVideo();
}

bool VDAVIOutputSegmentedSystem::AcceptsAudio() {
	return mpChildSystem->AcceptsAudio();
}

